/*
 * (C) 2009, Elephant Seven Hamburg Gmbh, 
 * Author: Detlev Wiese
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
 * use this file except in compliance with the License. You may obtain a copy 
 * of the License at
 *  
 *     http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.se and its accompanying notice file is
 * included with the distribution. 
 */ 
package com.e7.streams;

import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;

/**
 * <P>This class splits streams into sub-streams of equal length. The 
 * result of this operation is a stream of streams.</P> 
 * <P>The last sub-stream will carry less elements than the others, 
 * when there are not enough elements which can be read from the 
 * underlying stream.</P> 
 * @param <E> The type of the elements of the stream which is split.
 */
public class StreamOfStreams<E> extends AbstractStream<Stream<E>>{
	
	private Stream<E> stream; 
	private int count; 
	
	/**
	 * Create an instance! The stream returned will act as a stream 
	 * of streams, where each sub-stream has {@code count} elements.
	 * @param stream The stream to split
	 * @param count The number of elements per sub-stream.
	 */
	public StreamOfStreams(Stream<E> stream, int count) { 
		this.stream = stream;
		this.count = count; 
	}
	
	/**
	 * Syntactic sugar only. See
	 * {@link StreamOfStreams#StreamOfStreams(int, Stream)}.  
	 */
	public StreamOfStreams(int count, Stream<E> stream) { 
		this(stream, count);
	}
	
	public boolean hasNext() {
		return stream.hasNext();
	}

	public Stream<E> next() {
		if (stream.hasNext()) {
			int c = 0; 
			List<E> buffer = new ArrayList<E>(count);
			while (c++ < count && stream.hasNext())  
				buffer.add(stream.next());
				
			return new CollectionStream<E>(buffer);
		}
		throw new NoSuchElementException();
	}
}
